﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.Media.Capture;
using Windows.UI.Xaml.Media.Imaging;
using Windows.Storage;
using Windows.Media.MediaProperties;
using Windows.Devices.Enumeration;
using ZXing;
using WinRTXamlToolkit.Imaging;
using Infrastructure.UI;
using System.Diagnostics;
using Windows.Media.Devices;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using WinRTXamlToolkit.IO.Serialization;
using Windows.ApplicationModel.DataTransfer;
using Windows.UI.Core;
using Infrastructure;
using Windows.ApplicationModel.Resources;
using Windows.Storage.Search;
using Windows.Storage.Streams;

namespace Barcode
{
    public sealed partial class MainPage : Barcode.Common.LayoutAwarePage
    {
        DeviceInformation camera;
        MediaElement beep = new MediaElement();
        ResourceLoader loader = new ResourceLoader();

        bool scanning;

        public MainPage()
        {
            this.InitializeComponent();

            this.EnablePrivacyPolicy(PrivacyPolicy.RunXiaDianQi);

            Window.Current.VisibilityChanged += window_VisibilityChanged;
        }

        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
            InitializeCameraAsync();
        }

        protected override void SaveState(Dictionary<String, Object> pageState)
        {
        }

        private void window_VisibilityChanged(object sender, VisibilityChangedEventArgs e)
        {
            if (e.Visible)
            {
                if (camera != null)
                {
                    ScanAsync(camera);
                }
            }
            else
            {
                scanning = false;
            }
        }

        private void camerasComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            camera = (DeviceInformation)e.AddedItems[0];
            camera.Id.SerializeAsXml("Camera.xml");
            ScanAsync(camera);
        }

        private void copyButton_Click(object sender, RoutedEventArgs e)
        {
            var dataPackage = new DataPackage();
            dataPackage.RequestedOperation = DataPackageOperation.Copy;
            dataPackage.SetText(resultTextBox.Text);

            Clipboard.SetContent(dataPackage);
        }

        private async void InitializeCameraAsync()
        {
            var cameras = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);

            if (cameras.Count == 0)
            {
                MessageBox.Show(loader.GetString("NoCameraError"));
                return;
            }

            DefaultViewModel["Cameras"] = cameras;

            try
            {
                var id = await XmlSerialization.LoadFromXmlFile<string>("Camera.xml");
                camera = cameras.Where(c => c.Id == id).FirstOrDefault();

                if (camera != null)
                {
                    camerasComboBox.SelectedItem = camera;
                }
            }
            catch
            {
                camerasComboBox.SelectedIndex = 0;
            }

            StorageFolder beepFolder = await Package.Current.InstalledLocation.GetFolderAsync("Assets");
            StorageFile beepFile = await beepFolder.GetFileAsync("Beep.wav");
            var stream = await beepFile.OpenAsync(FileAccessMode.Read);
            beep.AutoPlay = false;
            beep.SetSource(stream, beepFile.ContentType);
        }


        private async void ScanAsync(DeviceInformation camera)
        {
            scanning = true;

            MediaCapture mc = new MediaCapture();

            await mc.InitializeAsync(
                new MediaCaptureInitializationSettings
                {
                    PhotoCaptureSource = PhotoCaptureSource.Auto,
                    StreamingCaptureMode = StreamingCaptureMode.Video,
                    VideoDeviceId = camera.Id
                });

            previewCaptureElement.Source = mc;

            await mc.StartPreviewAsync();

            var imageEncodingProperties = ImageEncodingProperties.CreateJpeg();
            var barcodeReader = new BarcodeReader();

            while (scanning)
            {
                try
                {
                    await Task.Delay(200);

                    var stream = new InMemoryRandomAccessStream();

                    await mc.CapturePhotoToStreamAsync(imageEncodingProperties, stream);

                    var photo = await BitmapFactory.New(1, 1).FromStream(stream);

                    var result = barcodeReader.Decode(photo);
                    
                    if (result != null)
                    {
                        resultTextBox.Text = result.Text;
                        beep.Play();
                        await Task.Delay(1000);
                    }
                }
                catch 
                {
                }
            }

            try
            {
                await mc.StopPreviewAsync();
            }
            catch
            {
            }
        }
    }
}
